#ifndef __REAL_STREAM_SOURCE_H__
#define __REAL_STREAM_SOURCE_H__

#include <list>
#include <stdio.h>
#include <map>
#include <mutex>
#include <memory>
#include <atomic>
#include <thread>
#include <functional>
#include "Util/util.h"
#include "Thread/Thread.h"
#include "frame_common.h"

namespace Media{

class VideoEncode;
class AudioEncode;

// struct VideoFormat{
//     uint16_t type;
//     uint16_t BitRate;
//     uint16_t Width;
//     uint16_t Height;
//     uint16_t Fps;
//     uint16_t GOP;
//     uint	 reserved[5];
//     VideoFormat():type(0),BitRate(0),Width(0),Height(0),Fps(0),GOP(0),reserved{0}{ }
// };

/// 流媒体数据源
//先不做继承,后面区分实时流源和文件流源,基类命名可命为LocalStreamSource,本地流源,分实时流源和文件流源
//RealStreamSource/FileStreamSource
//关于Encode配置管理,考虑不做Encode了,就做在这里,简单一点.
//另外Encode的配置本身也是只影响实时流的,等后面业务复杂了再考虑增加Encode管理.
class RealStreamSource : public std::enable_shared_from_this<RealStreamSource>
{
public:
	struct SourceKey{
		int _video = -1;
		int _audio = -1;
		bool operator <(const SourceKey& other) const{
			if(_video < other._video)
				return true;
			if(_audio < other._audio)
				return true;
			return false;
		}
		SourceKey(int video, int audio):_video(video), _audio(audio){

		}
	};

	using Ptr = std::shared_ptr<RealStreamSource>;
	// using CallBack = std::function<void(const Stream::Frame::Ptr &)>;
	using CallBack = std::function<void(const FrameCommon::Frame::Ptr &)>;
friend Ptr;
    using StreamMap = std::map<SourceKey/*StreamType*/, std::weak_ptr<RealStreamSource> >;
//    using ChannelStreamMap = std::unordered_map<int/*channel*/, StreamMap>;

	static Ptr create(int video, int audio);


	~RealStreamSource();
public:
	RealStreamSource(int video, int audio);
public:
	/// 销毁函数
	void destroy();

	bool start(void *thiz, const CallBack &callback);

	bool stop(void *thiz);

	bool clear();

	bool setIFrame();

	bool getVideoFormat(FrameCommon::VideoFormat *format);
private:
	/// 取帧数据回调函数
	//这里可以有两种做法
	//简单做法,直接在这里启线程,调用Encoder->getPacket,然后调用上层的回调。
	//另一种做法,如果存在线程切换不及时的问题,可以把这个回调传给编码器，编码器继续把回调传给底层，由底层来调到这个回调,这个时候不要启线程，线程是sdk层启的,不会有线程切换导致的滞后.
	// void onVideoPacket(const Stream::Frame::Ptr &frame);
	// void onAudioPacket(const Stream::Frame::Ptr &frame);

	void onVideoPacket(const FrameCommon::Frame::Ptr &frame);
	void onAudioPacket(const FrameCommon::Frame::Ptr &frame);

	void ThreadProc(Fdt::Thread *thread);

	bool setVideoFormat();

	bool setAudioFormat();

private:
	static StreamMap							s_streamMap;
	static std::recursive_mutex 				s_stream_mutex;

//	int 										_channel = 0;
//	int 										_stream = 0;
	int 										_video = 0;
	int 										_audio = 0;
	VideoEncode									*_videoenc;
	AudioEncode									*_audioenc;
	std::recursive_mutex						_video_mutex;
	std::recursive_mutex						_audio_mutex;

	std::map<void *, std::shared_ptr<CallBack>> _video_func_map;
	std::map<void *, std::shared_ptr<CallBack>> _audio_func_map;
	uint32_t _video_cnt = 0;
};

}//namespace Media

#endif //__REAL_STREAM_SOURCE_H__

